package com.hunk.core.dao;

import java.util.List;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import com.hunk.core.web.model.Page;

public class BaseDaoSpringJdbc<T> extends NamedParameterJdbcDaoSupport {
	/** oracle **/
//	protected final static String PAGE_SQL_PREFIX = "select * from(select m.*,rownum num from (";
//	protected final static String PAGE_SQL_END = ") m where limit <=?) where num>?";
	/** mysql **/
	protected final static String PAGE_SQL_PREFIX = "select * from ";
	protected final static String PAGE_SQL_END = " limit ?, ?";
	
	/**
	 * 适用于更新数据库,insert,update, delete
	 * 
	 * @param namedSql
	 *            :命名参数的 sql 语句，而且参数的命名必须和java bean 中的属性名对应
	 * @param javaBean
	 *            ：java bean 对象
	 * @return
	 */
	protected int update(String namedSql, Object javaBean) {
		SqlParameterSource paramSource = new BeanPropertySqlParameterSource(
				javaBean);
		return this.getNamedParameterJdbcTemplate().update(namedSql,paramSource);
	}

//	protected int commonUpdate(String sql, Object... paramValue) {
//		return this.getJdbcTemplate().update(sql, paramValue);
//	}

	public T getJavaBean(String sql, Class<T> returnType,
			Object... paramValue) {
		RowMapper<T> rowMapper = new BeanPropertyRowMapper<T>(returnType);
		try{
		return this.getJdbcTemplate()
				.queryForObject(sql, rowMapper, paramValue);
		}catch(Exception ex){
			return null;
		}
	}
	
	protected T getJavaBean(String sql, Class<T> clazz,
			T object) {
		SqlParameterSource sps = new BeanPropertySqlParameterSource(object);
		RowMapper<T> rowMapper = new BeanPropertyRowMapper<T>(clazz);
		try {
			return this.getNamedParameterJdbcTemplate()
				.queryForObject(sql, sps, rowMapper);
		} catch(Exception ex){
			ex.printStackTrace();
			return null;
		}
	}
	protected List<T> getList(String sql, Class<T> returnType,
			Object... paramValue) {
		RowMapper<T> rowMapper = new BeanPropertyRowMapper<T>(returnType);
		return this.getJdbcTemplate().query(sql, rowMapper, paramValue);
	}
	
	protected List<T> getList(String sql, Class<T> returnType) {
		RowMapper<T> rowMapper = new BeanPropertyRowMapper<T>(returnType);
		return this.getJdbcTemplate().query(sql, rowMapper);
	}

	/**
	 * 计算总记录数
	 * 
	 * @param countSQL
	 *            计算总记录数的count语句
	 * @param paramValue
	 *            语句中对应的参数值
	 * @return 总记录数
	 */
	protected int getCount(String countSQL, List<Object> paramValue) {
		return this.getJdbcTemplate().queryForInt(countSQL,
				paramValue.toArray());
	}

	protected int getCount(String countSQL, Object... paramValue) {
		return this.getJdbcTemplate().queryForInt(countSQL, paramValue);
	}

	/**
	 * @author HunkDeng
	 * @param page
	 * @param querySQL
	 * @param countSQL
	 * @param whereSQL
	 * @param paramList
	 * @param returnType
	 * @return
	 */
	public Page<T> getPageModel(Page<T> page,
			StringBuilder querySQL, StringBuilder countSQL,
			StringBuilder whereSQL, List<Object> paramList, Class<T> returnType) {
		querySQL.append(whereSQL);
		countSQL.append(whereSQL);
		// 计算总记录数
		int allCount = this.getCount(countSQL.toString(), paramList);
		// 重新计算页数，为了防止高并发后瞬间删光数据
		long pageCount = allCount % page.getPageSize() > 0 ? 
				allCount/page.getPageSize() + 1 :  allCount/page.getPageSize();
		// 核对请求的页数是否存在，不存在返回最后页
		long pageNo = page.getPageNo() > pageCount ? pageCount : page.getPageNo();
		
		// 获取分页记录集
		// 1。构造完整的分页语句
		querySQL.insert(0, PAGE_SQL_PREFIX);
		querySQL.append(PAGE_SQL_END);

		// 2.把分页语句中的参数值加入到paramList中
		paramList.add((pageNo - 1) * page.getPageSize());
		paramList.add(pageNo * page.getPageSize());
		
		List<T> result = this.getList(querySQL.toString(), returnType,
				paramList.toArray());
		Page<T> models = new Page<T>();
		models.setTotal(allCount);
		models.setPageNo(pageNo);
		models.setRows(result);
		models.setOrder(page.getOrder());
		models.setOrderBy(page.getOrderBy());
		return models;
	}
}